<html>
<head><meta charset="utf-8"><title>pub visibility in inner mod · t-lang · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/index.html">t-lang</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html">pub visibility in inner mod</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="221364829"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221364829" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> varkor <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221364829">(Jan 01 2021 at 19:21)</a>:</h4>
<p>Is there a good reason the following is rejected?</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">T</span><span class="p">;</span><span class="w"></span>

<span class="k">mod</span> <span class="nn">X</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">foo</span><span class="p">(</span><span class="n">t</span>: <span class="nc">crate</span>::<span class="n">T</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="c1">// error: private type `T` in public interface</span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p><code>crate::T</code> is public, but only to <code>X</code>, which itself has the same privacy as the outer crate and thus <code>T</code> itself. Couldn't this be accepted?</p>



<a name="221365678"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221365678" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> XAMPPRocky <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221365678">(Jan 01 2021 at 19:44)</a>:</h4>
<p>I’ve asked about this before, and I believe the answer was that you can still say <code>pub use X::foo;</code> which would be valid and so you’re still leaking a private type. The module’s visibility has no effect on the inner items.</p>



<a name="221365849"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221365849" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> varkor <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221365849">(Jan 01 2021 at 19:49)</a>:</h4>
<p>I would have thought <code>pub use X::foo</code> would be the same as <code>pub fn foo(t: T)</code> in the outer crate, which would emit an error because <code>T</code> is not <code>pub</code>.</p>



<a name="221373097"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221373097" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Christopher Durham <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221373097">(Jan 01 2021 at 22:53)</a>:</h4>
<p>The problem if I understand it correctly is locality of errors. Since <code>create::X::foo</code> is marked <code>pub</code>, you can at root level expose <code>pub use crate::X::foo</code>, at which point you do have a private type in an exported interface. Erroring at the definition of <code>foo</code> is nicer and more local than an error at the reexport of <code>foo</code>.</p>
<p>The standard solution is that <code>foo</code> should be <code>pub(crate)</code> instead of <code>pub</code> to the world.</p>



<a name="221373525"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221373525" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> varkor <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221373525">(Jan 01 2021 at 23:05)</a>:</h4>
<p>I personally think giving an error if you try to <code>pub use crate::X::foo</code> would be less surprising, but if others disagree then this is certainly more conservative.</p>



<a name="221637026"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221637026" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> XAMPPRocky <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221637026">(Jan 05 2021 at 11:41)</a>:</h4>
<p>I definitely agree it is confusing, and I have been caught by it when you have a public type in your interface such as a function, but it isn't actually reachable for end users, and even worse it's not documented aside from at the function site. I think it might be nice to have a clippy lint for it.</p>



<a name="221666610"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221666610" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221666610">(Jan 05 2021 at 16:21)</a>:</h4>
<p>Like this? <a href="https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unreachable-pub">https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unreachable-pub</a></p>



<a name="221677596"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221677596" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> pachi <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221677596">(Jan 05 2021 at 17:44)</a>:</h4>
<p>And isn't allowing pub items inside private ones a problem for safe transmute? <span class="user-mention" data-user-id="219211">@Jack Wrenn</span> maybe just for types...</p>



<a name="221679131"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221679131" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221679131">(Jan 05 2021 at 17:56)</a>:</h4>
<p>@pachi The connection between the pub-and-priv trick and transmutation is this: Transmutation-like operations allow you to directly muck with fields. Directly mucking with a field you don't have visibility on is unsound. So, any complete analysis of the safety of such an operation needs to account for visibility. The pub-in-priv trick complicates visibility analysis. Without it, you can assess the visibility of a field just by looking at the visibility modifier on that field, and the type that it's apart of. With the pub-in-priv trick, you also need to account for module visibility.</p>



<a name="221679828"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221679828" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> pachi <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221679828">(Jan 05 2021 at 18:01)</a>:</h4>
<p>Thanks! I thought this could be relevant to your (impressive) work on safe transmute.</p>



<a name="221680527"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221680527" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221680527">(Jan 05 2021 at 18:06)</a>:</h4>
<p>IIRC, type privacy basically has two aspects to it:</p>
<ul>
<li>(incomplete) lints that nudge you away from declaring unreachable types</li>
<li>a complete reachability-based analysis that stops you from using private types</li>
</ul>
<p>At one time, the hope was that it featuring public types in private interfaces could be made an error, but this broke way too much code on <a href="http://crates.io">crates.io</a>. (To this day, unreachable types continues to be the only way to achieve 'sealed' traits, for instance.) The fallout was this:</p>
<ul>
<li>a few cases which now get no warning whatsoever (namely, the pub-in-priv trick)</li>
<li>a few cases that remain warnings but can be replaced with the pub-in-priv trick, and thus might be made hard errors in the future</li>
<li>a few hard errors</li>
</ul>
<p>I think <span class="user-mention" data-user-id="121053">@varkor</span>'s example is an instance of that last category.</p>
<p>In principle, all of these lints for priv-in-pub are unnecessary for soundness, because of the reachability-based <a href="https://github.com/rust-lang/rfcs/pull/2145">type privacy</a> analysis by <span class="user-mention" data-user-id="123856">@Vadim Petrochenkov</span>. This analysis targets the use-sites of private types.</p>



<a name="221680784"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/pub%20visibility%20in%20inner%20mod/near/221680784" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/pub.20visibility.20in.20inner.20mod.html#221680784">(Jan 05 2021 at 18:08)</a>:</h4>
<p>Type privacy <em>is</em> essential to the soundness of the latest iteration of the safe transmute proposal, and I think to some other things already in Rust, too.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>